//---------------------------------------------------------------------
// Includes
//---------------------------------------------------------------------
#include "Dataset.hpp"
#include "../Vision/VisionTools.hpp"
#include <sstream>

//---------------------------------------------------------------------
// Constantes
//---------------------------------------------------------------------
#define DEFAULT_IMAGE_SIZE -1

namespace Calibration
{
	///////////////////////////////////////////////////////////////////
	/// Constructeur
	///////////////////////////////////////////////////////////////////
	CalibrationDataset::CalibrationDataset():
	imagesHeight(DEFAULT_IMAGE_SIZE),imagesWidth(DEFAULT_IMAGE_SIZE)
	{
		
	}
	
	///////////////////////////////////////////////////////////////////
	/// Destructeur
	///////////////////////////////////////////////////////////////////
	CalibrationDataset::~CalibrationDataset()
	{
		ImagesVector::iterator it;
		for( it = imagesVector.begin(); it != imagesVector.end(); it++ )
		{		
			if( *it != NULL) 
			{
				// On libère l'image
				cvReleaseImage(&(*it));
			}
		}
		imagesVector.clear();
	}
	
	///////////////////////////////////////////////////////////////////
	/// Accesseur d'image
	///////////////////////////////////////////////////////////////////
	IplImage* CalibrationDataset::operator[]( unsigned int index )
	{
		IplImage* image = NULL;
		Assert( index < imagesVector.size() );
		image = imagesVector[index];
		return image;	
	}
	
	///////////////////////////////////////////////////////////////////
	/// Retourne le nombre d'image de calibrage
	///////////////////////////////////////////////////////////////////
	int CalibrationDataset::GetNumberOfImages()
	{
		return imagesVector.size();
	}
	
	///////////////////////////////////////////////////////////////////
	/// Retourne le nombre d'image de calibrage
	///////////////////////////////////////////////////////////////////
	int CalibrationDataset::GetWidthOfImages()
	{
		return imagesWidth;
	}
	
	///////////////////////////////////////////////////////////////////
	/// Retourne le nombre d'image de calibrage
	///////////////////////////////////////////////////////////////////
	int CalibrationDataset::GetHeightOfImages()
	{
		return imagesHeight;
	}
	
	///////////////////////////////////////////////////////////////////
	// Chargement d'une image depuis un fichier
	///////////////////////////////////////////////////////////////////
	void CalibrationDataset::AddImageFromFile( std::string filename ) throw (Tools::LoadingFailed,Tools::InvalidImageSize)
	{
		//Chargement de l'image
		IplImage* image = cvLoadImage(filename.c_str());
		if( image == NULL )
		{
			throw Tools::LoadingFailed(filename,"Chargement de l'image impossible");
		}
		else
		{
			// Vérification de la résolution de l'image
			if(!CorrectImageSize(image))
			{	
				int width = image->width;
				int height = image->height;
				cvReleaseImage(&image);
				std::ostringstream error;
				error << "Taille attendu [w:" << imagesWidth << ",h:" << imagesHeight << "]"; 
				throw Tools::InvalidImageSize(width,height,error.str());
			}			
			
			// Transformation de l'image pour la rendre compatible avec la fonction de calibrage
			// -> mise en niveau de gris sur 8 bits
			IplImage* tempImage = NULL;
			tempImage = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_8U,1);
			cvConvertImage(image, tempImage);
			cvReleaseImage(&image);			
			
			// Ajout de l'image à la collection
			imagesVector.push_back(tempImage);
			
			// Affichage image (DEBUG)
			//Vision::VisionTools::DrawImage( "DataSet::FromFile", 1000, tempImage );
		}
		
	}
	
	///////////////////////////////////////////////////////////////////
	// Chargement d'une image depuis la camera
	///////////////////////////////////////////////////////////////////
	void CalibrationDataset::AddImageFromCamera( Vision::Camera * camera ) throw (Tools::InvalidDevice,Tools::InvalidImageSize)
	{
		// Prise d'image
		IplImage* image = NULL;
		if( camera != NULL )
		{
			image = camera->CapturePicture();
		} 		
					
		if( image == NULL )
		{
			throw Tools::InvalidDevice( "Prise d'image impossible" );
		}
		else
		{		
			// Vérification de la résolution de l'image
			if(!CorrectImageSize(image))
			{
				std::ostringstream error;
				error << "Taille attendu [w:" << imagesWidth << ",h:" << imagesHeight << "]"; 
				throw Tools::InvalidImageSize(image->width,image->height,error.str());
			}
			
			// Transformation de l'image pour la rendre compatible avec la fonction de calibrage
			// -> mise en niveau de gris sur 8 bits
			IplImage* tempImage = NULL;
			tempImage = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_8U,1);
			cvConvertImage(image, tempImage);			
			
			// Ajout de l'image à la collection
			imagesVector.push_back(tempImage);	
			
			// Affichage image (DEBUG)
			//Vision::VisionTools::DrawImage( "DataSet::FromCamera", 1000, tempImage );	
		}				
	}
	
	///////////////////////////////////////////////////////////////////
	// Vérifie la validité de la taille de l'image
	//  Précondition : image non nulle
	///////////////////////////////////////////////////////////////////
	bool CalibrationDataset::CorrectImageSize( IplImage * image )
	{
		if( (imagesHeight == DEFAULT_IMAGE_SIZE) || (imagesWidth == DEFAULT_IMAGE_SIZE) )
		{
			imagesHeight = image->height;
			imagesWidth = image->width;
		}
		
		return (imagesHeight == image->height) && (imagesWidth == image->width);
		  
	}

}
